package org.goldfish.demo.multifrontend.messageboard.mobile.network

import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import org.goldfish.demo.multifrontend.messageboard.mobile.MyApp
import retrofit2.HttpException
import java.io.IOException

/**
 * 网络异常处理工具类
 */
private val TAG = NetworkException::class.java.name

object NetworkException {

    /**
     * Handles API errors, navigating to LoginActivity for 4xx errors,
     * and showing Toasts for other errors.
     *
     * @param activity The current ComponentActivity.
     * @param exception The exception caught.
     * @param httpErrorMessageClient Toast message for client HTTP errors (non-4xx).
     * @param httpErrorMessageServer Toast message for server HTTP errors.
     * @param showToast Optional flag to show toast, default is true
     * @param onAuthError Optional callback for authentication errors (4xx), default is null
     */
    fun handleApiError(
        activity: ComponentActivity,
        exception: Exception,
        httpErrorMessageClient: String? = null,
        httpErrorMessageServer: String? = null,
        showToast: Boolean = true,
        onAuthError: (() -> Unit)? = null
    ) {
        when (exception) {
            is HttpException -> {
                if (exception.code() in 400..499) {
                    Logger.e("HTTP 4xx error: ${exception.code()}", exception)
                    onAuthError?.invoke()
                } else {
                    // Use existing toast handler for other HTTP errors (e.g., 5xx)
                    handleHttpExceptionWithToast(
                        activity,
                        exception,
                        clientErrorMessage = httpErrorMessageClient, // This will be used if it's somehow a 4xx not caught above
                        serverErrorMessage = httpErrorMessageServer,
                        showToast = showToast
                    )
                }
            }

            is IOException -> {
                handleNetworkExceptionWithToast(activity, exception, showToast = showToast)
            }

            else -> {
                handleOtherExceptionWithToast(activity, exception, showToast = showToast)
            }
        }
    }

    /**
     * 处理Retrofit的HttpException并直接显示Toast
     *
     * @param context 上下文对象
     * @param e HttpException实例
     * @param clientErrorMessage 客户端错误(4xx)时显示的消息，默认为null(使用默认消息)
     * @param serverErrorMessage 服务端错误(5xx)时显示的消息，默认为null(使用默认消息)
     * @param duration Toast显示时长，默认为Toast.LENGTH_SHORT
     * @param showToast 是否显示Toast，默认为true
     */
    fun handleHttpExceptionWithToast(
        context: Context,
        e: HttpException,
        clientErrorMessage: String? = null,
        serverErrorMessage: String? = null,
        duration: Int = Toast.LENGTH_SHORT,
        showToast: Boolean = true
    ) {
        val code = e.code()
        e.message()

        when (code) {
            in 400..499 -> {
                val msg = clientErrorMessage ?: "客户端错误 $code: 请求参数有误或权限不足"
                Logger.e("HTTP client error $code: $msg", e)
                if (showToast) {
                    Toast.makeText(context, msg, duration).show()
                }
            }

            in 500..599 -> {
                val msg = serverErrorMessage ?: "服务器错误 $code: 服务器暂时不可用"
                Logger.e("HTTP server error $code: $msg", e)
                if (showToast) {
                    Toast.makeText(context, msg, duration).show()
                }
            }

            else -> {
                val msg = "HTTP error $code: ${e.message()}"
                Logger.e("HTTP other error $code: $msg", e)
                if (showToast) {
                    Toast.makeText(context, msg, duration).show()
                }
            }
        }
    }

    /**
     * 处理网络连接异常并直接显示Toast
     *
     * @param context 上下文对象
     * @param e IOException实例
     * @param message 自定义错误消息，默认为null(使用默认消息)
     * @param duration Toast显示时长，默认为Toast.LENGTH_SHORT
     * @param showToast 是否显示Toast，默认为true
     */
    fun handleNetworkExceptionWithToast(
        context: Context,
        e: IOException,
        message: String? = null,
        duration: Int = Toast.LENGTH_SHORT,
        showToast: Boolean = true
    ) {
        val errorMsg = message ?: "网络连接异常，请检查网络设置"
        Logger.e(errorMsg, e)
        if (showToast) {
            Toast.makeText(context, errorMsg, duration).show()
        }
    }

    /**
     * 处理其他网络相关异常并直接显示Toast
     *
     * @param context 上下文对象
     * @param e Exception实例
     * @param message 自定义错误消息，默认为null(使用默认消息)
     * @param duration Toast显示时长，默认为Toast.LENGTH_SHORT
     * @param showToast 是否显示Toast，默认为true
     */
    fun handleOtherExceptionWithToast(
        context: Context,
        e: Exception,
        message: String? = null,
        duration: Int = Toast.LENGTH_SHORT,
        showToast: Boolean = true
    ) {
        val errorMsg = message ?: "发生未知错误: ${e.message}"
        Logger.e( errorMsg,e)
        if (showToast) {
            Toast.makeText(context, errorMsg, duration).show()
        }
    }
}

object Logger {
    enum class LogLevel(val priority: Int) {
        DEBUG(1),
        INFO(2),
        WARN(3),
        ERROR(4)
    }

    private var logLevel: LogLevel = LogLevel.DEBUG
    private const val FALLBACK_TAG = "AppLogger"

    private fun getRealTag(): String {
        val packageName = MyApp.appContext.packageName
        Thread.currentThread().stackTrace.forEach { stack ->
            val clazz = stack.className
            if (clazz.startsWith(packageName) && clazz != Logger::class.java.name) {
                return clazz.substringAfterLast('.')
            }
        }
        return FALLBACK_TAG
    }

    private fun log(level: LogLevel, msg: String, throwable: Throwable? = null): Int {
        if (level.priority < logLevel.priority) return -1
        val tag = getRealTag()

        // 打主 log，保证 throwable 能打印
        throwable?.let {
            Log.println(Log.getStackTraceString(it).lines().size, tag, "$msg\n${Log.getStackTraceString(it)}")
        }

        return when (level) {
            LogLevel.DEBUG -> if (throwable != null) Log.d(tag, msg, throwable) else Log.d(tag, msg)
            LogLevel.INFO  -> if (throwable != null) Log.i(tag, msg, throwable) else Log.i(tag, msg)
            LogLevel.WARN  -> if (throwable != null) Log.w(tag, msg, throwable) else Log.w(tag, msg)
            LogLevel.ERROR -> if (throwable != null) Log.e(tag, msg, throwable) else Log.e(tag, msg)
        }
    }

    // 便捷函数
    fun d(msg: String, throwable: Throwable? = null) = log(LogLevel.DEBUG, msg, throwable)
    fun i(msg: String, throwable: Throwable? = null) = log(LogLevel.INFO, msg, throwable)
    fun w(msg: String, throwable: Throwable? = null) = log(LogLevel.WARN, msg, throwable)
    fun e(msg: String, throwable: Throwable? = null) = log(LogLevel.ERROR, msg, throwable)
}
